package lobby;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map.Entry;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.json.simple.JSONObject;
import org.json.simple.JSONValue;

@WebServlet("/gameInstance")
public class GameInstance extends HttpServlet {
	
	//Helper class for every gameinstance
	private class GameIn{
		public boolean isPlayer1() {
			return player1;
		}
		public void setPlayer1(boolean player1) {
			this.player1 = player1;
		}
		public boolean isPlayer2() {
			return player2;
		}
		public void setPlayer2(boolean player2) {
			this.player2 = player2;
		}
		public JSONObject getP1ShipsDep() {
			return p1ShipsDep;
		}
		
		public int getP1Left() {
			return p1Left;
		}
		public void setP1Left(int p1Left) {
			this.p1Left = p1Left;
		}
		public int getP2Left() {
			return p2Left;
		}
		public void setP2Left(int p2Left) {
			this.p2Left = p2Left;
		}
		
		public int getP1gameStatus() {
			return p1gameStatus;
		}
		public void setP1gameStatus(int p1gameStatus) {
			this.p1gameStatus = p1gameStatus;
		}
		public int getP2gameStatus() {
			return p2gameStatus;
		}
		public void setP2gameStatus(int p2gameStatus) {
			this.p2gameStatus = p2gameStatus;
		}
		public boolean isPlayer1Dep() {
			return player1Dep;
		}
		public void setPlayer1Dep(boolean player1Dep) {
			this.player1Dep = player1Dep;
		}
		public boolean isPlayer2Dep() {
			return player2Dep;
		}
		public void setPlayer2Dep(boolean player2Dep) {
			this.player2Dep = player2Dep;
		}
		public JSONObject getP2ShipsDep() {
			return p2ShipsDep;
		}
		public void setP2ShipsDep(JSONObject p2ShipsDep) {
			this.p2ShipsDep = p2ShipsDep;
		}
		public JSONObject getP1Ships() {
			return p1Ships;
		}
		public void setP1Ships(JSONObject p1Ships) {
			this.p1Ships = p1Ships;
		}
		public JSONObject getP2Ships() {
			return p2Ships;
		}
		public void setP2Ships(JSONObject p2Ships) {
			this.p2Ships = p2Ships;
		}
		public void setP1ShipsDep(JSONObject p1ShipsDep) {
			this.p1ShipsDep = p1ShipsDep;
		}
		public JSONObject getP1ShipLoc() {
			return p1ShipLoc;
		}
		public void setP1ShipLoc(JSONObject p1ShipLoc) {
			this.p1ShipLoc = p1ShipLoc;
		}
		public JSONObject getP2ShipLoc() {
			return p2ShipLoc;
		}
		public void setP2ShipLoc(JSONObject p2ShipLoc) {
			this.p2ShipLoc = p2ShipLoc;
		}
		public String getP1LastHit() {
			return p1LastHit;
		}
		public void setP1LastHit(String p1LastHit) {
			this.p1LastHit = p1LastHit;
		}
		public String getP2LastHit() {
			return p2LastHit;
		}
		public void setP2LastHit(String p2LastHit) {
			this.p2LastHit = p2LastHit;
		}
		public int getP1HitStatus() {
			return p1HitStatus;
		}
		public void setP1HitStatus(int p1HitStatus) {
			this.p1HitStatus = p1HitStatus;
		}
		public int getP2HitStatus() {
			return p2HitStatus;
		}
		public void setP2HitStatus(int p2HitStatus) {
			this.p2HitStatus = p2HitStatus;
		}






		boolean player1 = true;
		boolean player2 = false;
		boolean player1Dep = false;
		boolean player2Dep = false;
		// Hash, cell key, ship/null value
		JSONObject p1ShipsDep;
		JSONObject p2ShipsDep;
		//Hash ship key, int of amount of cells left value
		JSONObject p1Ships;
		JSONObject p2Ships;
		//Hash ship key, array of ship locations
		JSONObject p1ShipLoc;
		JSONObject p2ShipLoc;
		// Which cell was last hit, used to mark where oppenent's bomb landed
		String p1LastHit;
		String p2LastHit;
		// hitStatus : 0 - miss, 1 - hit, 2 - drowned
		int p1HitStatus;
		int p2HitStatus;
		// Ships left, if 0, game over
		int p1Left = 20;
		int p2Left = 20;
		//GameStatus:  0 - dep, 1- your turn, 2-wait for opponent
		int p1gameStatus = 0;
		int p2gameStatus = 0;
		private GameIn()
		{}
	}
	
	public String toJson(ArrayList<String> input) {
		JSONObject json = new JSONObject();
		for(int i=0;i<(input.size());i=i+2){
			json.put(input.get(i),input.get(i+1));
		}
		return json.toJSONString();
	}
	
	HashMap<Integer,GameIn> games = new HashMap<Integer,GameIn>();
	
	
	public void doPost(HttpServletRequest request,
 			 HttpServletResponse response)
	throws ServletException, IOException {
		int status = Integer.parseInt(request.getParameter("status"));
		HttpSession session = request.getSession(true);
		if (status == 0)
		{
			int id = Integer.parseInt(request.getParameter("id"));
			if (!(games.containsKey(id)))
			{
				games.put(id, new GameIn());
				session.setAttribute("player", 1);
				session.setAttribute("id", id);
				
			}
			else
			{
				games.get(id).setPlayer2(true);
				session.setAttribute("player", 2);
				session.setAttribute("id", id);
			}
	
		}
		else if (status == 1)
		{
			int player =(Integer) session.getAttribute("player");
			int id = (Integer) session.getAttribute("id");
			if (Integer.parseInt(request.getParameter("confirm"))==1)
			{
				if (player==1)
				{
					GameIn game = games.get(id);
					game.setPlayer1Dep(true);
					Object tempShips = JSONValue.parse(request.getParameter("ships"));
					game.setP1Ships((JSONObject) tempShips);
					Object tempCells = JSONValue.parse(request.getParameter("cells"));
					game.setP1ShipsDep((JSONObject) tempCells);
					Object tempShipLoc = JSONValue.parse(request.getParameter("shipLocs"));
					game.setP1ShipLoc((JSONObject) tempShipLoc);
					games.put(id, game);
				}
				else
				{
					GameIn game = games.get(id);
					game.setPlayer2Dep(true);
					Object tempShips = JSONValue.parse(request.getParameter("ships"));
					game.setP2Ships((JSONObject) tempShips);
					Object tempCells = JSONValue.parse(request.getParameter("cells"));
					game.setP2ShipsDep((JSONObject) tempCells);
					Object tempShipLoc = JSONValue.parse(request.getParameter("shipLocs"));
					game.setP2ShipLoc((JSONObject) tempShipLoc);
					games.put(id, game);
				}
			}
			else
			{
				if (player==1)
				{
					GameIn game = games.get(id);
					game.setPlayer1Dep(false);
					games.put(id, game);
				}
				else
				{
					GameIn game = games.get(id);
					game.setPlayer2Dep(false);
					games.put(id, game);
				}

			}
		}
		else if (status==2)
		{
			// hitStatus : 0 - miss, 1 - hit, 2 - drowned
			int hitStatus;
			int player =(Integer) session.getAttribute("player");
			int id = (Integer) session.getAttribute("id");
			GameIn game = games.get(id);
			ArrayList<String> json = new ArrayList<String>();
			JSONObject cells;
			JSONObject ships;
			JSONObject shipLoc;
			if (player ==1)
			{
				cells = game.getP2ShipsDep();
				ships = game.getP2Ships();
				shipLoc = game.getP2ShipLoc();
			}
			else
			{
				cells = game.getP1ShipsDep();
				ships = game.getP1Ships();
				shipLoc = game.getP1ShipLoc();
			}
			String jsonCell = request.getParameter("cell");
			String cell = (String) cells.get(jsonCell);
			  if (cell!=null)  
			  {
				  cells.put(jsonCell, null);
				  json.add("hit");
				  json.add("true");
				  if ( ((Long) ships.get(cell)).intValue()==1)
				  {
					  json.add("drown");
					  json.add(shipLoc.get(cell).toString());
					  hitStatus = 2;
				  }
				  else
				  {
					  ships.put(cell,((Integer)(((Long) ships.get(cell)).intValue()-1)).longValue() );
					  hitStatus = 1;
					  if (player==1)
					  {
						  game.setP2Ships(ships);
					  }
					  else
					  {
						  game.setP1Ships(ships);
					  }
				  }
				  int left;
				  if (player ==1)
				  {
					  left = game.getP2Left();
					  if (left==1)
					  {
						  game.setP1gameStatus(3);
						  game.setP2gameStatus(4);
					  }
					  else
					  {
						  game.setP2Left(left-1);
					  }
				  }
				  else
				  {
					  left = game.getP1Left();
					  if (left==1)
					  {
						  game.setP1gameStatus(4);
						  game.setP2gameStatus(3);
					  }
					  else
					  {
						  game.setP1Left(left-1);
					  }
				  }
			  }
			  else
			  {
				  hitStatus = 0;
				  json.add("hit");
				  json.add("false");
				  // Vaheta aktiivne mangija
				  if (game.getP1gameStatus()==1)
				  {
					  game.setP1gameStatus(2);
					  game.setP2gameStatus(1);
				  }
				  else
				  {
					  game.setP1gameStatus(1);
					  game.setP2gameStatus(2);
				  }
			  }
			if (player == 1)
			{
				game.setP2LastHit(jsonCell);
				game.setP2HitStatus(hitStatus);
			}
			else
			{
				game.setP1LastHit(jsonCell);
				game.setP1HitStatus(hitStatus);
			}
			PrintWriter out = response.getWriter();
			out.print(toJson(json));
			out.flush();
		}
		else if (status==3)
		{
			int player =(Integer) session.getAttribute("player");
			int id = (Integer) session.getAttribute("id");
			GameIn game = games.get(id);
			if (player ==1)
			{
				game.setP1gameStatus(4);
				game.setP2gameStatus(3);
			 }
			else
			{
				game.setP1gameStatus(3);
				game.setP2gameStatus(4);
			}
				 
			  
		}
		
		

	}
	
	public void doGet(HttpServletRequest request,
            HttpServletResponse response)
	throws ServletException, IOException {
		ArrayList<String> json = new ArrayList<String>();
		HttpSession session = request.getSession();
		int player = (Integer) session.getAttribute("player");
		int id = (Integer) session.getAttribute("id");
		GameIn game = games.get(id);
		int status;
		String lastHit;
		int hitStatus;
		if (player==1)
		{
			status = game.getP1gameStatus();
			lastHit = game.getP1LastHit();
			hitStatus = game.getP1HitStatus();
		}
		else
		{
			status = game.getP2gameStatus();
			lastHit = game.getP2LastHit();
			hitStatus = game.getP2HitStatus();
		}
		if (status==0)
		{
			if (game.isPlayer1Dep()&&game.isPlayer2Dep())
			{
				game.setP1gameStatus(1);
				game.setP2gameStatus(2);
				games.put(id,game);
				
			}
		}
		json.add("gameStatus");
		json.add(Integer.toString(status));
		json.add("lastHit");
		json.add(lastHit);
		json.add("hitStatus");
		json.add(Integer.toString(hitStatus));
		PrintWriter out = response.getWriter();
		out.print(toJson(json));
		out.flush();
		
		
		
	}
	
}
